﻿Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Windows.Forms

Namespace System.Workflow.ComponentModel.Design
    Friend Class ConnectorRouter
        ' Methods
        Private Shared Sub AddBoundPoint(ByRef extremitiesList As List([Of] DistanceFromPoint), ByVal p As Point, ByVal segment As ConnectorSegment, ByVal Z As Point)
            If (((p.X <> -2147483648) AndAlso (p.X <> &H7FFFFFFF)) AndAlso ((p.Y <> -2147483648) AndAlso (p.Y <> &H7FFFFFFF))) Then
                extremitiesList.Add(New DistanceFromPoint(segment, Z, p))
            End If
        End Sub

        Private Shared Function EscapeAlgorithm(ByVal coverSet As CoverSet, ByVal Z As Point, ByVal targetPoint As Point, ByRef LeA As List([Of] Point), ByRef LhA As List([Of] ConnectorSegment), ByRef LvA As List([Of] ConnectorSegment), ByRef LhB As List([Of] ConnectorSegment), ByRef LvB As List([Of] ConnectorSegment), ByRef orientationA As Orientation, <Out> ByRef intersectionSegmentA As ConnectorSegment, <Out> ByRef intersectionSegmentB As ConnectorSegment, ByVal margin As Size, ByRef noEscapeA As Boolean) As Nullable([Of] Point)
            Dim flag2 As Boolean
            Dim flag3 As Boolean
            Dim flag4 As Boolean
            Dim flag5 As Boolean
            Dim nullable As Nullable([Of] Point) = Nothing
            intersectionSegmentA = Nothing
            intersectionSegmentB = Nothing
            Dim cover As ConnectorSegment = coverSet.GetCover(Z, DesignerEdges.Left)
            Dim segment2 As ConnectorSegment = coverSet.GetCover(Z, DesignerEdges.Right)
            Dim segment3 As ConnectorSegment = coverSet.GetCover(Z, DesignerEdges.Bottom)
            Dim segment4 As ConnectorSegment = coverSet.GetCover(Z, DesignerEdges.Top)
            Dim item As ConnectorSegment = ConnectorSegment.SegmentFromLeftToRightCover(coverSet, Z)
            LhA.Add(item)
            Dim segment6 As ConnectorSegment = ConnectorSegment.SegmentFromBottomToTopCover(coverSet, Z)
            LvA.Add(segment6)
            Dim i As Integer
            For i = 0 To LvB.Count - 1
                Dim segment As ConnectorSegment = LvB.Item(i)
                nullable = item.Intersect(segment)
                If nullable.HasValue Then
                    intersectionSegmentA = item
                    intersectionSegmentB = segment
                    Return nullable
                End If
            Next i
            Dim j As Integer
            For j = 0 To LhB.Count - 1
                Dim segment8 As ConnectorSegment = LhB.Item(j)
                nullable = segment6.Intersect(segment8)
                If nullable.HasValue Then
                    intersectionSegmentA = segment6
                    intersectionSegmentB = segment8
                    Return nullable
                End If
            Next j
            Dim nullable2 As Nullable([Of] Point) = ConnectorRouter.EscapeProcessI(coverSet, Z, segment6, Orientation.Horizontal, margin)
            If nullable2.HasValue Then
                orientationA = Orientation.Vertical
                LeA.Add(nullable2.Value)
                Return Nothing
            End If
            nullable2 = ConnectorRouter.EscapeProcessI(coverSet, Z, item, Orientation.Vertical, margin)
            If nullable2.HasValue Then
                orientationA = Orientation.Horizontal
                LeA.Add(nullable2.Value)
                Return Nothing
            End If
            Dim intersectionFlag As Boolean = False
            Dim empty As Point = Point.Empty
            Dim r As Point = Point.Empty
            Dim point3 As Point = Point.Empty
            Dim point4 As Point = Point.Empty
            If (Not segment4 Is Nothing) Then
                empty = New Point(Z.X, segment4.A.Y)
            End If
            If (Not segment2 Is Nothing) Then
                r = New Point(segment2.A.X, Z.Y)
            End If
            If (Not segment3 Is Nothing) Then
                point3 = New Point(Z.X, segment3.A.Y)
            End If
            If (Not cover Is Nothing) Then
                point4 = New Point(cover.A.X, Z.Y)
            End If
            Do
                flag2 = flag3 = flag4 = flag5 = False
                If (Not segment4 Is Nothing) Then
                    empty.Y = (empty.Y - margin.Height)
                    If (empty.Y > Z.Y) Then
                        flag2 = True
                        Dim nullable3 As Nullable([Of] Point) = ConnectorRouter.EscapeProcessII(coverSet, Orientation.Vertical, (LeA), (LhA), (LvA), (LhB), (LvB), Z, empty, margin, intersectionFlag, intersectionSegmentA, intersectionSegmentB)
                        If nullable3.HasValue Then
                            LvA.Add(segment6)
                            If intersectionFlag Then
                                Return nullable3
                            End If
                            orientationA = Orientation.Horizontal
                            coverSet.AddUsedEscapeLine(New ConnectorSegment(Z, empty))
                            coverSet.AddUsedEscapeLine(New ConnectorSegment(empty, nullable3.Value))
                            LeA.Add(nullable3.Value)
                            Return Nothing
                        End If
                    End If
                End If
                If (Not segment2 Is Nothing) Then
                    r.X = (r.X - margin.Width)
                    If (r.X > Z.X) Then
                        flag3 = True
                        Dim nullable4 As Nullable([Of] Point) = ConnectorRouter.EscapeProcessII(coverSet, Orientation.Horizontal, (LeA), (LhA), (LvA), (LhB), (LvB), Z, r, margin, intersectionFlag, intersectionSegmentA, intersectionSegmentB)
                        If nullable4.HasValue Then
                            LhA.Add(item)
                            If intersectionFlag Then
                                Return nullable4
                            End If
                            orientationA = Orientation.Vertical
                            coverSet.AddUsedEscapeLine(New ConnectorSegment(Z, r))
                            coverSet.AddUsedEscapeLine(New ConnectorSegment(r, nullable4.Value))
                            LeA.Add(nullable4.Value)
                            Return Nothing
                        End If
                    End If
                End If
                If (Not segment3 Is Nothing) Then
                    point3.Y = (point3.Y + margin.Height)
                    If (point3.Y < Z.Y) Then
                        flag4 = True
                        Dim nullable5 As Nullable([Of] Point) = ConnectorRouter.EscapeProcessII(coverSet, Orientation.Vertical, (LeA), (LhA), (LvA), (LhB), (LvB), Z, point3, margin, intersectionFlag, intersectionSegmentA, intersectionSegmentB)
                        If nullable5.HasValue Then
                            LvA.Add(segment6)
                            If intersectionFlag Then
                                Return nullable5
                            End If
                            orientationA = Orientation.Horizontal
                            coverSet.AddUsedEscapeLine(New ConnectorSegment(Z, point3))
                            coverSet.AddUsedEscapeLine(New ConnectorSegment(point3, nullable5.Value))
                            LeA.Add(nullable5.Value)
                            Return Nothing
                        End If
                    End If
                End If
                If (Not cover Is Nothing) Then
                    point4.X = (point4.X + margin.Width)
                    If (point4.X < Z.X) Then
                        flag5 = True
                        Dim nullable6 As Nullable([Of] Point) = ConnectorRouter.EscapeProcessII(coverSet, Orientation.Horizontal, (LeA), (LhA), (LvA), (LhB), (LvB), Z, point4, margin, intersectionFlag, intersectionSegmentA, intersectionSegmentB)
                        If nullable6.HasValue Then
                            LhA.Add(item)
                            If intersectionFlag Then
                                Return nullable6
                            End If
                            orientationA = Orientation.Vertical
                            coverSet.AddUsedEscapeLine(New ConnectorSegment(Z, point4))
                            coverSet.AddUsedEscapeLine(New ConnectorSegment(point4, nullable6.Value))
                            LeA.Add(nullable6.Value)
                            Return Nothing
                        End If
                    End If
                End If
            Loop While ((flag2 OrElse flag3) OrElse (flag4 OrElse flag5))
            noEscapeA = True
            Return Nothing
        End Function

        Private Shared Function EscapeProcessI(ByVal coverSet As CoverSet, ByVal Z As Point, ByVal escapeLine As ConnectorSegment, ByVal orientation As Orientation, ByVal margin As Size) As Nullable([Of] Point)
            Dim extremitiesList As New List([Of] DistanceFromPoint)(4)
            Dim cover As ConnectorSegment = coverSet.GetCover(Z, If((orientation = Orientation.Horizontal), DesignerEdges.Left, DesignerEdges.Bottom))
            If (Not cover Is Nothing) Then
                ConnectorRouter.AddBoundPoint((extremitiesList), cover.A, cover, Z)
                ConnectorRouter.AddBoundPoint((extremitiesList), cover.B, cover, Z)
            End If
            Dim segment As ConnectorSegment = coverSet.GetCover(Z, If((orientation = Orientation.Horizontal), DesignerEdges.Right, DesignerEdges.Top))
            If (Not segment Is Nothing) Then
                ConnectorRouter.AddBoundPoint((extremitiesList), segment.A, segment, Z)
                ConnectorRouter.AddBoundPoint((extremitiesList), segment.B, segment, Z)
            End If
            If (extremitiesList.Count <> 0) Then
                DistanceSorter.Sort((extremitiesList))
                Dim i As Integer
                For i = 0 To extremitiesList.Count - 1
                    Dim edges As DesignerEdges
                    Dim point3 As Point
                    Dim p As Point = extremitiesList.Item(i).P
                    Dim point2 As New Point(Math.Sign(CInt((p.X - Z.X))), Math.Sign(CInt((p.Y - Z.Y))))
                    If (If((orientation = Orientation.Vertical), point2.X, point2.Y) = 0) Then
                        p = extremitiesList.Item(i).ConnectorSegment.ExtendPointOutwards(p)
                        point2 = New Point(Math.Sign(CInt((p.X - Z.X))), Math.Sign(CInt((p.Y - Z.Y))))
                        p = extremitiesList.Item(i).P
                    End If
                    If (orientation = Orientation.Vertical) Then
                        edges = If((point2.Y < 0), DesignerEdges.Bottom, DesignerEdges.Top)
                    Else
                        edges = If((point2.X < 0), DesignerEdges.Left, DesignerEdges.Right)
                    End If
                    If (orientation = Orientation.Vertical) Then
                        point3 = New Point((p.X + (point2.X * margin.Width)), Z.Y)
                    Else
                        point3 = New Point(Z.X, (p.Y + (point2.Y * margin.Height)))
                    End If
                    Dim segment4 As New ConnectorSegment(Z, point3)
                    If (((Not coverSet.EscapeLineHasBeenUsed(segment4, point3) AndAlso escapeLine.IsPointOnSegment(point3)) AndAlso ((escapeLine.A <> point3) AndAlso (escapeLine.B <> point3))) AndAlso coverSet.IsEscapePoint(Z, point3, edges)) Then
                        coverSet.AddUsedEscapeLine(segment4)
                        Return New Nullable([Of] Point)(point3)
                    End If
                Next i
            End If
            Return Nothing
        End Function

        Private Shared Function EscapeProcessII(ByVal coverSet As CoverSet, ByVal orientation As Orientation, ByRef LeA As List([Of] Point), ByRef LhA As List([Of] ConnectorSegment), ByRef LvA As List([Of] ConnectorSegment), ByRef LhB As List([Of] ConnectorSegment), ByRef LvB As List([Of] ConnectorSegment), ByVal Z As Point, ByVal R As Point, ByVal margin As Size, <Out> ByRef intersectionFlag As Boolean, <Out> ByRef intersectionSegmentA As ConnectorSegment, <Out> ByRef intersectionSegmentB As ConnectorSegment) As Nullable([Of] Point)
            intersectionFlag = False
            intersectionSegmentA = Nothing
            intersectionSegmentB = Nothing
            Dim escapeLine As ConnectorSegment = ConnectorSegment.SegmentFromLeftToRightCover(coverSet, R)
            Dim segment2 As ConnectorSegment = ConnectorSegment.SegmentFromBottomToTopCover(coverSet, R)
            Dim i As Integer
            For i = 0 To LvB.Count - 1
                Dim segment As ConnectorSegment = LvB.Item(i)
                Dim nullable As Nullable([Of] Point) = escapeLine.Intersect(segment)
                If nullable.HasValue Then
                    intersectionFlag = True
                    intersectionSegmentA = escapeLine
                    intersectionSegmentB = segment
                    LeA.Add(R)
                    Return nullable
                End If
            Next i
            Dim j As Integer
            For j = 0 To LhB.Count - 1
                Dim segment4 As ConnectorSegment = LhB.Item(j)
                Dim nullable2 As Nullable([Of] Point) = segment2.Intersect(segment4)
                If nullable2.HasValue Then
                    intersectionFlag = True
                    intersectionSegmentA = segment2
                    intersectionSegmentB = segment4
                    LeA.Add(R)
                    Return nullable2
                End If
            Next j
            Dim nullable3 As Nullable([Of] Point) = Nothing
            If (orientation = Orientation.Horizontal) Then
                nullable3 = ConnectorRouter.EscapeProcessI(coverSet, R, segment2, Orientation.Horizontal, margin)
                If nullable3.HasValue Then
                    LvA.Add(segment2)
                    LeA.Add(R)
                    Return nullable3
                End If
                nullable3 = ConnectorRouter.EscapeProcessI(coverSet, R, escapeLine, Orientation.Vertical, margin)
                If nullable3.HasValue Then
                    LhA.Add(escapeLine)
                    LeA.Add(R)
                    Return nullable3
                End If
            Else
                nullable3 = ConnectorRouter.EscapeProcessI(coverSet, R, escapeLine, Orientation.Vertical, margin)
                If nullable3.HasValue Then
                    LhA.Add(escapeLine)
                    LeA.Add(R)
                    Return nullable3
                End If
                nullable3 = ConnectorRouter.EscapeProcessI(coverSet, R, segment2, Orientation.Horizontal, margin)
                If nullable3.HasValue Then
                    LvA.Add(segment2)
                    LeA.Add(R)
                    Return nullable3
                End If
            End If
            Return Nothing
        End Function

        Private Shared Function FirstRefinementAlgorithm(ByVal Le As List([Of] Point), ByVal intersection As Point, ByVal intersectionSegment As ConnectorSegment) As List([Of] Point)
            Dim point As Point
            Dim list As New List([Of] Point)
            Dim segment As ConnectorSegment = intersectionSegment
            Do While (Le.Count > 0)
                Dim index As Integer = (Le.Count - 1)
                Do While (Not segment.PointLiesOnThisLine(Le.Item(index)) AndAlso (index > 0))
                    index -= 1
                Loop
                Do While ((index > 0) AndAlso segment.PointLiesOnThisLine(Le.Item((index - 1))))
                    index -= 1
                Loop
                point = Le.Item(index)
                list.Add(point)
                Do While (Le.Count > index)
                    Le.RemoveAt(index)
                Loop
                segment = segment.PeprendecularThroughPoint(point)
            Loop
            Return list
        End Function

        Private Shared Function GetRoutedLineSegments(ByVal begin As Point, ByVal [end] As Point, ByVal margin As Size, ByVal rectanglesToExclude As Rectangle(), ByVal linesToExclude As Point()) As Point()
            If (rectanglesToExclude Is Nothing) Then
                Throw New ArgumentNullException("rectanglesToExclude")
            End If
            If (linesToExclude Is Nothing) Then
                Throw New ArgumentNullException("linesToExclude")
            End If
            If ((linesToExclude.Length Mod 2) > 0) Then
                Throw New ArgumentException(DR.GetString("Error_Connector2", New Object(0  - 1) {}))
            End If
            Dim coverSet As New CoverSet(rectanglesToExclude, linesToExclude)
            coverSet.ClearUsedLines
            Dim point As Point = begin
            Dim point2 As Point = [end]
            Dim leA As New List([Of] Point)
            Dim le As New List([Of] Point)
            Dim lhA As New List([Of] ConnectorSegment)
            Dim lvA As New List([Of] ConnectorSegment)
            Dim lhB As New List([Of] ConnectorSegment)
            Dim lvB As New List([Of] ConnectorSegment)
            Dim horizontal As Orientation = Orientation.Horizontal
            Dim orientation2 As Orientation = Orientation.Horizontal
            leA.Add(begin)
            le.Add([end])
            Dim noEscapeA As Boolean = False
            Dim flag2 As Boolean = False
            Dim nullable As Nullable([Of] Point) = Nothing
            Dim intersectionSegmentA As ConnectorSegment = Nothing
            Dim intersectionSegmentB As ConnectorSegment = Nothing
            Try 
            Label_00A1:
                Do While noEscapeA
                    If flag2 Then
                        goto Label_0172
                    End If
                    Dim list7 As List([Of] Point) = leA
                    leA = le
                    le = list7
                    Dim point3 As Point = point
                    point = point2
                    point2 = point3
                    Dim flag3 As Boolean = noEscapeA
                    noEscapeA = flag2
                    flag2 = flag3
                    Dim orientation3 As Orientation = horizontal
                    horizontal = orientation2
                    orientation2 = orientation3
                    Dim list8 As List([Of] ConnectorSegment) = lhA
                    lhA = lhB
                    lhB = list8
                    list8 = lvA
                    lvA = lvB
                    lvB = list8
                Loop
                Dim z As Point = leA.Item((leA.Count - 1))
                Dim targetPoint As Point = point2
                nullable = ConnectorRouter.EscapeAlgorithm(coverSet, z, targetPoint, (leA), (lhA), (lvA), (lhB), (lvB), (horizontal), intersectionSegmentA, intersectionSegmentB, margin, (noEscapeA))
                If Not nullable.HasValue Then
                    Dim list9 As List([Of] Point) = leA
                    leA = le
                    le = list9
                    Dim point6 As Point = point
                    point = point2
                    point2 = point6
                    Dim flag4 As Boolean = noEscapeA
                    noEscapeA = flag2
                    flag2 = flag4
                    Dim orientation4 As Orientation = horizontal
                    horizontal = orientation2
                    orientation2 = orientation4
                    Dim list10 As List([Of] ConnectorSegment) = lhA
                    lhA = lhB
                    lhB = list10
                    list10 = lvA
                    lvA = lvB
                    lvB = list10
                    goto Label_00A1
                End If
            Label_0172:
                If Not nullable.HasValue Then
                    Return Nothing
                End If
                Dim refinedPath As New List([Of] Point)
                leA = ConnectorRouter.FirstRefinementAlgorithm(leA, nullable.Value, intersectionSegmentA)
                le = ConnectorRouter.FirstRefinementAlgorithm(le, nullable.Value, intersectionSegmentB)
                Dim i As Integer = (leA.Count - 1)
                Do While (i >= 0)
                    refinedPath.Add(leA.Item(i))
                    i -= 1
                Loop
                refinedPath.Add(nullable.Value)
                Dim j As Integer
                For j = 0 To le.Count - 1
                    refinedPath.Add(le.Item(j))
                Next j
                ConnectorRouter.SecondRefinementAlgorithm(coverSet, (refinedPath), margin)
                If ((refinedPath.Count > 1) AndAlso (refinedPath.Item((refinedPath.Count - 1)) Is begin)) Then
                    refinedPath.Reverse
                End If
                Return refinedPath.ToArray
            Catch obj1 As Object
                Return Nothing
            End Try
        End Function

        Public Shared Function Route(ByVal begin As Point, ByVal [end] As Point, ByVal margin As Size, ByVal enclosingRectangle As Rectangle, ByVal rectanglesToExclude As Rectangle(), ByVal linesToExclude As Point(), ByVal pointsToExclude As Point()) As Point()
            Dim list As New List([Of] Rectangle)(rectanglesToExclude)
            If Not enclosingRectangle.IsEmpty Then
                begin.X = Math.Min(Math.Max(begin.X, (enclosingRectangle.Left + 1)), (enclosingRectangle.Right - 1))
                begin.Y = Math.Min(Math.Max(begin.Y, (enclosingRectangle.Top + 1)), (enclosingRectangle.Bottom - 1))
                list.Insert(0, enclosingRectangle)
            End If
            Dim list2 As New List([Of] Point)(linesToExclude)
            Dim num As Integer = Math.Max((margin.Width / 2), 1)
            Dim num2 As Integer = Math.Max((margin.Height / 2), 1)
            Dim point As Point
            For Each point In pointsToExclude
                list2.Add(New Point((point.X - num), point.Y))
                list2.Add(New Point((point.X + num), point.Y))
                list2.Add(New Point(point.X, (point.Y - num2)))
                list2.Add(New Point(point.X, (point.Y + num2)))
            Next
            Return ConnectorRouter.GetRoutedLineSegments(begin, [end], margin, list.ToArray, list2.ToArray)
        End Function

        Private Shared Sub SecondRefinementAlgorithm(ByVal coverSet As CoverSet, ByRef refinedPath As List([Of] Point), ByVal margin As Size)
            Dim num As Integer
            Dim list As New List([Of] Point)
            num
            For num = 0 To (refinedPath.Count - 1) - 1
                Dim a As Point = refinedPath.Item(num)
                Dim b As Point = refinedPath.Item((num + 1))
                Dim segment As ConnectorSegment = ConnectorSegment.ConstructBoundSegment(coverSet, a, b)
                Dim num2 As Integer = (num + 2)
                Do While (num2 < (refinedPath.Count - 1))
                    Dim point3 As Point = refinedPath.Item(num2)
                    Dim point4 As Point = refinedPath.Item((num2 + 1))
                    Dim segment2 As ConnectorSegment = ConnectorSegment.ConstructBoundSegment(coverSet, point3, point4)
                    Dim nullable As Nullable([Of] Point) = segment.Intersect(segment2)
                    If nullable.HasValue Then
                        list.Clear
                        Dim i As Integer = 0
                        Do While (i <= num)
                            list.Add(refinedPath.Item(i))
                            i += 1
                        Loop
                        list.Add(nullable.Value)
                        Dim j As Integer
                        For j = (num2 + 1) To refinedPath.Count - 1
                            list.Add(refinedPath.Item(j))
                        Next j
                        Dim list2 As List([Of] Point) = refinedPath
                        refinedPath = list
                        list = list2
                        list.Clear
                        num2 = (num + 2)
                    Else
                        num2 += 1
                    End If
                Loop
            Next num
            num = 0
            Do While (num < (refinedPath.Count - 1))
                Dim point5 As Point = refinedPath.Item(num)
                Dim point6 As Point = refinedPath.Item((num + 1))
                Dim flag As Boolean = False
                Dim segment3 As ConnectorSegment = ConnectorSegment.ConstructBoundSegment(coverSet, point5, point6)
                If (Not segment3 Is Nothing) Then
                    Dim point7 As New Point((point6.X - point5.X), (point6.Y - point5.Y))
                    Dim num5 As Integer = Math.Max(Math.Abs(CInt((point7.X / margin.Width))), Math.Abs(CInt((point7.Y / margin.Height))))
                    point7.X = Math.Sign(point7.X)
                    point7.Y = Math.Sign(point7.Y)
                    Dim k As Integer = 1
                    Do While (k <= num5)
                        Dim point8 As New Point((point5.X + ((k * margin.Width) * point7.X)), (point5.Y + ((k * margin.Height) * point7.Y)))
                        If (point8 = point6) Then
                            Exit Do
                        End If
                        Dim segment4 As ConnectorSegment = ConnectorSegment.ConstructBoundSegment(coverSet, point8, If((segment3.Orientation = Orientation.Horizontal), Orientation.Vertical, Orientation.Horizontal))
                        Dim m As Integer = (num + 2)
                        Do While ((m < (refinedPath.Count - 1)) AndAlso Not flag)
                            Dim point9 As Point = refinedPath.Item(m)
                            Dim point10 As Point = refinedPath.Item((m + 1))
                            Dim segment5 As New ConnectorSegment(point9, point10)
                            Dim nullable2 As Nullable([Of] Point) = segment4.Intersect(segment5)
                            If (nullable2.HasValue AndAlso segment5.IsPointOnSegment(nullable2.Value)) Then
                                flag = True
                                list.Clear
                                Dim n As Integer = 0
                                Do While (n <= num)
                                    list.Add(refinedPath.Item(n))
                                    n += 1
                                Loop
                                list.Add(point8)
                                list.Add(nullable2.Value)
                                Dim num9 As Integer
                                For num9 = (m + 1) To refinedPath.Count - 1
                                    list.Add(refinedPath.Item(num9))
                                Next num9
                                Dim list3 As List([Of] Point) = refinedPath
                                refinedPath = list
                                list3.Clear
                                Exit Do
                            End If
                            m += 1
                        Loop
                        If flag Then
                            Exit Do
                        End If
                        k += 1
                    Loop
                End If
                If Not flag Then
                    num += 1
                End If
            Loop
        End Sub


        ' Fields
        Private Shared ReadOnly DefaultSize As Size = New Size(4, 4)

        ' Nested Types
        <DebuggerDisplay("Segment ( {A.X}, {A.Y} ) - ( {B.X},{B.Y} ), {Orientation}")> _
        Private NotInheritable Class ConnectorSegment
            ' Methods
            Public Sub New(ByVal point1 As Point, ByVal point2 As Point)
                If ((point1.X <> point2.X) AndAlso (point1.Y <> point2.Y)) Then
                    Throw New InvalidOperationException(SR.GetString("Error_InvalidConnectorSegment"))
                End If
                Me.point1 = point1
                Me.point2 = point2
                Me.orientation = If((Me.point1.X = Me.point2.X), Orientation.Vertical, Orientation.Horizontal)
            End Sub

            Public Shared Function ConstructBoundSegment(ByVal coverSet As CoverSet, ByVal a As Point, ByVal b As Point) As ConnectorSegment
                If ((a.X <> b.X) AndAlso (a.Y <> b.Y)) Then
                    Return Nothing
                End If
                Return ConnectorSegment.ConstructBoundSegment(coverSet, a, If((a.X = b.X), Orientation.Vertical, Orientation.Horizontal))
            End Function

            Public Shared Function ConstructBoundSegment(ByVal coverSet As CoverSet, ByVal a As Point, ByVal orientation As Orientation) As ConnectorSegment
                If (orientation <> Orientation.Horizontal) Then
                    Return ConnectorSegment.SegmentFromBottomToTopCover(coverSet, a)
                End If
                Return ConnectorSegment.SegmentFromLeftToRightCover(coverSet, a)
            End Function

            Public Function Covers(ByVal p As Point) As Boolean
                If (Me.orientation <> Orientation.Horizontal) Then
                    Return ((p.Y >= Math.Min(Me.point1.Y, Me.point2.Y)) AndAlso (p.Y <= Math.Max(Me.point1.Y, Me.point2.Y)))
                End If
                Return ((p.X >= Math.Min(Me.point1.X, Me.point2.X)) AndAlso (p.X <= Math.Max(Me.point1.X, Me.point2.X)))
            End Function

            Public Shared Function DistanceBetweenPoints(ByVal p As Point, ByVal q As Point) As Double
                Return Math.Sqrt((((p.X - q.X) * (p.X - q.X)) + ((p.Y - q.Y) * (p.Y - q.Y))))
            End Function

            Public Overrides Function Equals(ByVal obj As Object) As Boolean
                Dim segment As ConnectorSegment = [TryCast](obj,ConnectorSegment)
                If (segment Is Nothing) Then
                    Return False
                End If
                Return (((Me.point1 = segment.A) AndAlso (Me.point2 = segment.B)) AndAlso (Me.Orientation = segment.Orientation))
            End Function

            Public Function ExtendPointOutwards(ByVal p As Point) As Point
                If ((p <> Me.point1) AndAlso (p <> Me.point2)) Then
                    Return p
                End If
                Dim num As Integer = If((Me.orientation = Orientation.Horizontal), p.X, p.Y)
                Dim num2 As Integer = If((Me.orientation = Orientation.Horizontal), Me.point1.X, Me.point1.Y)
                Dim num3 As Integer = If((Me.orientation = Orientation.Horizontal), Me.point2.X, Me.point2.Y)
                If (num = Math.Min(num2, num3)) Then
                    num -= 1
                Else
                    num += 1
                End If
                Return New Point(If((Me.orientation = Orientation.Horizontal), num, p.X), If((Me.orientation = Orientation.Horizontal), p.Y, num))
            End Function

            Public Overrides Function GetHashCode() As Integer
                Return ((Me.point1.GetHashCode Xor Me.point2.GetHashCode) Xor Me.Orientation.GetHashCode)
            End Function

            Public Function Intersect(ByVal segment As ConnectorSegment) As Nullable([Of] Point)
                If (Me.orientation <> segment.Orientation) Then
                    Dim segment2 As ConnectorSegment = If((Me.orientation = Orientation.Vertical), Me, segment)
                    Dim segment3 As ConnectorSegment = If((Me.orientation = Orientation.Vertical), segment, Me)
                    If ((segment2.A.X < Math.Min(segment3.A.X, segment3.B.X)) OrElse (segment2.A.X > Math.Max(segment3.A.X, segment3.B.X))) Then
                        Return Nothing
                    End If
                    If ((segment3.A.Y >= Math.Min(segment2.A.Y, segment2.B.Y)) AndAlso (segment3.A.Y <= Math.Max(segment2.A.Y, segment2.B.Y))) Then
                        Return New Point(segment2.A.X, segment3.A.Y)
                    End If
                End If
                Return Nothing
            End Function

            Public Function IsPointOnSegment(ByVal p As Point) As Boolean
                If (((Me.orientation = Orientation.Horizontal) AndAlso (p.Y <> Me.point1.Y)) OrElse ((Me.orientation = Orientation.Vertical) AndAlso (p.X <> Me.point1.X))) Then
                    Return False
                End If
                Dim num As Integer = If((Me.orientation = Orientation.Horizontal), p.X, p.Y)
                Dim num2 As Integer = If((Me.orientation = Orientation.Horizontal), Me.point1.X, Me.point1.Y)
                Dim num3 As Integer = If((Me.orientation = Orientation.Horizontal), Me.point2.X, Me.point2.Y)
                Return ((num >= Math.Min(num2, num3)) AndAlso (num <= Math.Max(num2, num3)))
            End Function

            Public Function PeprendecularThroughPoint(ByVal p As Point) As ConnectorSegment
                Dim orientation As Orientation = If((Me.orientation = Orientation.Horizontal), Orientation.Vertical, Orientation.Horizontal)
                Dim point As New Point(p.X, p.Y)
                If (orientation = Orientation.Horizontal) Then
                    point.X = &H7FFFFFFF
                Else
                    point.Y = &H7FFFFFFF
                End If
                Return New ConnectorSegment(p, point)
            End Function

            Public Function PointLiesOnThisLine(ByVal p As Point) As Boolean
                If (Me.orientation <> Orientation.Horizontal) Then
                    Return (p.X = Me.point1.X)
                End If
                Return (p.Y = Me.point1.Y)
            End Function

            Public Shared Function SegmentFromBottomToTopCover(ByVal coverSet As CoverSet, ByVal p As Point) As ConnectorSegment
                Dim cover As ConnectorSegment = coverSet.GetCover(p, DesignerEdges.Bottom)
                Dim segment2 As ConnectorSegment = coverSet.GetCover(p, DesignerEdges.Top)
                Dim point As New Point(p.X, If((Not cover Is Nothing), cover.A.Y, -2147483648))
                Return New ConnectorSegment(point, New Point(p.X, If((Not segment2 Is Nothing), segment2.A.Y, &H7FFFFFFF)))
            End Function

            Public Shared Function SegmentFromLeftToRightCover(ByVal coverSet As CoverSet, ByVal p As Point) As ConnectorSegment
                Dim cover As ConnectorSegment = coverSet.GetCover(p, DesignerEdges.Left)
                Dim segment2 As ConnectorSegment = coverSet.GetCover(p, DesignerEdges.Right)
                Dim point As New Point(If((Not cover Is Nothing), cover.A.X, -2147483648), p.Y)
                Return New ConnectorSegment(point, New Point(If((Not segment2 Is Nothing), segment2.A.X, &H7FFFFFFF), p.Y))
            End Function


            ' Properties
            Public ReadOnly Property A As Point
                Get
                    Return Me.point1
                End Get
            End Property

            Public ReadOnly Property B As Point
                Get
                    Return Me.point2
                End Get
            End Property

            Public ReadOnly Property Orientation As Orientation
                Get
                    Return Me.orientation
                End Get
            End Property


            ' Fields
            Private orientation As Orientation
            Private point1 As Point
            Private point2 As Point
        End Class

        Private NotInheritable Class CoverSet
            ' Methods
            Public Sub New(ByVal rectanglesToExclude As Rectangle(), ByVal linesToExclude As Point())
                Dim rectangle As Rectangle
                For Each rectangle In rectanglesToExclude
                    Me.AddCover(New ConnectorSegment(New Point(rectangle.Left, rectangle.Top), New Point(rectangle.Left, rectangle.Bottom)))
                    Me.AddCover(New ConnectorSegment(New Point(rectangle.Right, rectangle.Top), New Point(rectangle.Right, rectangle.Bottom)))
                    Me.AddCover(New ConnectorSegment(New Point(rectangle.Left, rectangle.Top), New Point(rectangle.Right, rectangle.Top)))
                    Me.AddCover(New ConnectorSegment(New Point(rectangle.Left, rectangle.Bottom), New Point(rectangle.Right, rectangle.Bottom)))
                Next
                Dim i As Integer
                For i = 0 To (linesToExclude.Length / 2) - 1
                    Me.AddCover(New ConnectorSegment(linesToExclude((i * 2)), linesToExclude(((i * 2) + 1))))
                Next i
            End Sub

            Public Sub AddCover(ByVal cover As ConnectorSegment)
                Dim list As List([Of] ConnectorSegment) = If((cover.Orientation = Orientation.Vertical), Me.verticalCovers, Me.horizontalCovers)
                Dim i As Integer
                For i = 0 To list.Count - 1
                    Dim segment As ConnectorSegment = list.Item(i)
                    If (cover.IsPointOnSegment(segment.A) AndAlso cover.IsPointOnSegment(segment.B)) Then
                        list.RemoveAt(i)
                        Exit For
                    End If
                    If (segment.IsPointOnSegment(cover.A) AndAlso segment.IsPointOnSegment(cover.B)) Then
                        Return
                    End If
                Next i
                list.Add(cover)
            End Sub

            Public Sub AddUsedEscapeLine(ByVal segment As ConnectorSegment)
                Me.usedEscapeLine.Add(segment)
            End Sub

            Public Sub ClearUsedLines()
                Me.usedEscapeLine.Clear
            End Sub

            Public Function EscapeLineHasBeenUsed(ByVal segment As ConnectorSegment, ByVal escapePoint As Point) As Boolean
                Dim i As Integer
                For i = 0 To Me.usedEscapeLine.Count - 1
                    Dim segment2 As ConnectorSegment = Me.usedEscapeLine.Item(i)
                    If segment2.IsPointOnSegment(escapePoint) Then
                        Return True
                    End If
                Next i
                Return False
            End Function

            Public Function GetCover(ByVal p As Point, ByVal side As DesignerEdges) As ConnectorSegment
                Dim segment As ConnectorSegment = Nothing
                Dim num As Integer = 0
                If ((side = DesignerEdges.Left) OrElse (side = DesignerEdges.Right)) Then
                    Dim j As Integer
                    For j = 0 To Me.verticalCovers.Count - 1
                        Dim segment2 As ConnectorSegment = Me.verticalCovers.Item(j)
                        Dim num3 As Integer = If((side = DesignerEdges.Left), (p.X - segment2.A.X), (segment2.A.X - p.X))
                        If (((num3 > 0) AndAlso segment2.Covers(p)) AndAlso ((segment Is Nothing) OrElse (num > num3))) Then
                            segment = segment2
                            num = num3
                        End If
                    Next j
                    Return segment
                End If
                Dim i As Integer
                For i = 0 To Me.horizontalCovers.Count - 1
                    Dim segment3 As ConnectorSegment = Me.horizontalCovers.Item(i)
                    Dim num5 As Integer = If((side = DesignerEdges.Bottom), (p.Y - segment3.A.Y), (segment3.A.Y - p.Y))
                    If (((num5 > 0) AndAlso segment3.Covers(p)) AndAlso ((segment Is Nothing) OrElse (num > num5))) Then
                        segment = segment3
                        num = num5
                    End If
                Next i
                Return segment
            End Function

            Public Function GetCovers(ByVal p As Point, ByVal side As DesignerEdges) As List([Of] ConnectorSegment)
                Dim list As New List([Of] ConnectorSegment)
                If ((side = DesignerEdges.Left) OrElse (side = DesignerEdges.Right)) Then
                    Dim j As Integer
                    For j = 0 To Me.verticalCovers.Count - 1
                        Dim item As ConnectorSegment = Me.verticalCovers.Item(j)
                        Dim num2 As Integer = If((side = DesignerEdges.Left), (p.X - item.A.X), (item.A.X - p.X))
                        If ((num2 > 0) AndAlso item.Covers(p)) Then
                            list.Add(item)
                        End If
                    Next j
                    Return list
                End If
                Dim i As Integer
                For i = 0 To Me.horizontalCovers.Count - 1
                    Dim segment2 As ConnectorSegment = Me.horizontalCovers.Item(i)
                    Dim num4 As Integer = If((side = DesignerEdges.Bottom), (p.Y - segment2.A.Y), (segment2.A.Y - p.Y))
                    If ((num4 > 0) AndAlso segment2.Covers(p)) Then
                        list.Add(segment2)
                    End If
                Next i
                Return list
            End Function

            Public Function IsEscapePoint(ByVal origin As Point, ByVal escape As Point, ByVal side As DesignerEdges) As Boolean
                Dim num As Integer
                Dim cover As ConnectorSegment = Me.GetCover(origin, side)
                If ((side = DesignerEdges.Left) OrElse (side = DesignerEdges.Right)) Then
                    num = (cover.A.X - escape.X)
                Else
                    num = (cover.A.Y - escape.Y)
                End If
                If cover.Covers(escape) Then
                    Return False
                End If
                Dim covers As List([Of] ConnectorSegment) = Me.GetCovers(escape, side)
                Dim i As Integer
                For i = 0 To covers.Count - 1
                    Dim num3 As Integer
                    Dim segment2 As ConnectorSegment = covers.Item(i)
                    If (segment2 Is cover) Then
                        Return False
                    End If
                    If ((side = DesignerEdges.Left) OrElse (side = DesignerEdges.Right)) Then
                        num3 = Math.Abs(CInt((segment2.A.X - escape.X)))
                    Else
                        num3 = Math.Abs(CInt((segment2.A.Y - escape.Y)))
                    End If
                    If ((Math.Sign(num3) = Math.Sign(num)) AndAlso (Math.Abs(num3) < Math.Abs(num))) Then
                        Return False
                    End If
                Next i
                Return True
            End Function


            ' Fields
            Private horizontalCovers As List([Of] ConnectorSegment) = New List([Of] ConnectorSegment)
            Private usedEscapeLine As List([Of] ConnectorSegment) = New List([Of] ConnectorSegment)
            Private verticalCovers As List([Of] ConnectorSegment) = New List([Of] ConnectorSegment)
        End Class

        <StructLayout(LayoutKind.Sequential)> _
        Private Structure DistanceFromPoint
            Public ConnectorSegment As ConnectorSegment
            Public P As Point
            Public Distance As Double
            Public Sub New(ByVal segment As ConnectorSegment, ByVal z As Point, ByVal p As Point)
                Me.ConnectorSegment = segment
                Me.P = p
                Me.Distance = ConnectorSegment.DistanceBetweenPoints(z, p)
            End Sub
        End Structure

        Private NotInheritable Class DistanceSorter
            Implements IComparer([Of] DistanceFromPoint)
            ' Methods
            Private Sub New()
            End Sub

            Public Shared Sub Sort(ByRef distances As List([Of] DistanceFromPoint))
                Dim comparer As New DistanceSorter
                distances.Sort(comparer)
            End Sub

            Private Function System.Collections.Generic.IComparer<System.Workflow.ComponentModel.Design.ConnectorRouter.DistanceFromPoint>.Compare(ByVal lhs As DistanceFromPoint, ByVal rhs As DistanceFromPoint) As Integer Implements IComparer([Of] DistanceFromPoint).Compare
                If (lhs.Distance = rhs.Distance) Then
                    Return 0
                End If
                If (lhs.Distance > rhs.Distance) Then
                    Return 1
                End If
                Return -1
            End Function

        End Class
    End Class
End Namespace

